/*
 * ***** BEGIN LICENSE BLOCK ***** Version: NPL 1.1/GPL 2.0/LGPL 2.1 The
 * contents of this file are subject to the Netscape Public License Version 1.1
 * (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.mozilla.org/NPL/
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License. The
 * Original Code is lutsko.com code. The Initial Developer of the Original Code
 * is James Lutsko. Portions created by the Initial Developer are Copyright (C)
 * 2003 the Initial Developer. All Rights Reserved. Contributor(s):
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or the
 * GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which
 * case the provisions of the GPL or the LGPL are applicable instead of those
 * above. If you wish to allow use of your version of this file only under the
 * terms of either the GPL or the LGPL, and not to allow others to use your
 * version of this file under the terms of the NPL, indicate your decision by
 * deleting the provisions above and replace them with the notice and other
 * provisions required by the GPL or the LGPL. If you do not delete the
 * provisions above, a recipient may use your version of this file under the
 * terms of any one of the NPL, the GPL or the LGPL. ***** END LICENSE BLOCK
 * *****
 */

package autoteam.tables;

import java.awt.Dimension;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;

import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

import autoteam.Team;
import autoteam.ui.Coord;
import autoteam.ui.CoordSelection;

/**
 * This is an example of a component, which serves as a DragSource as well as
 * Drop Target. To illustrate the concept, JList has been used as a droppable
 * target and a draggable source. Any component can be used instead of a JList.
 * The code also contains debugging messages which can be used for diagnostics
 * and understanding the flow of events.
 * 
 * @version 1.0
 */

public class DNDTable extends JTable implements DropTargetListener, DragSourceListener, DragGestureListener
{
	private static final long serialVersionUID = -2951038113038023572L;

	// enables this component to be a dropTarget
    DropTarget dropTarget = null;
    
    // enables this component to be a Drag Source
    DragSource dragSource = null;

    private ChildCellRenderer childCellRenderer;
    
    /**
     * constructor - initializes the DropTarget and DragSource.
     */
    public DNDTable( AbstractTableModel a )
    {
		super( a );
		dropTarget = new DropTarget( this, this );
		dragSource = new DragSource( );
		dragSource.createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_MOVE, this );
		
		setChildCellRenderer( new ChildCellRenderer( ) );
	
		this.setMaximumSize( new Dimension( 1600, 720 ) );
		this.setPreferredScrollableViewportSize( new Dimension( 720, 400 ) );
		this.setMinimumSize( new Dimension( 480, 320 ) );
    }
    
    public void formatColumns( )
    {
	for ( int i = 0; i < getColumnModel( ).getColumnCount( ); i++ )
	{
	    getColumnModel( ).getColumn( i ).setPreferredWidth( 200 );
	    getColumnModel( ).getColumn( i ).setCellRenderer( getChildCellRenderer() );
	}
    }

    /**
     * is invoked when you are dragging over the DropSite
     */
    
    public void dragEnter( DropTargetDragEvent event )
    {
	
	// debug messages for diagnostics
	// System.out.println( "dragEnter");
	event.acceptDrag( DnDConstants.ACTION_MOVE );
    }
    
    /**
     * is invoked when you are exit the DropSite without dropping
     */
    
    public void dragExit( DropTargetEvent event )
    {
    }
    
    /**
     * is invoked when a drag operation is going on
     */
    
    public void dragOver( DropTargetDragEvent event )
    {
    }
    
    /**
     * a drop has occurred
     */
    
    public void drop( DropTargetDropEvent event )
    {
	try
	{
	    Transferable transferable = event.getTransferable( );
	    
	    // we accept only Coords
	    if ( transferable.isDataFlavorSupported( CoordSelection.coordFlavor ) )
	    {
		
		event.acceptDrop( DnDConstants.ACTION_MOVE );
		
		Coord s = (Coord) transferable.getTransferData( CoordSelection.coordFlavor );
		String msg = null;
		DraftTeamsTableModel model = (DraftTeamsTableModel) ((MapTableModel) getModel( )).getModel( );
		msg =
		      model.CheckSwitch( s.col, s.row, columnAtPoint( event.getLocation( ) ),
					 rowAtPoint( event.getLocation( ) ) );
		if ( msg != null )
		    if ( JOptionPane.showConfirmDialog( this, msg, "Warning", JOptionPane.YES_NO_OPTION,
							JOptionPane.WARNING_MESSAGE ) != JOptionPane.YES_OPTION )
			return;
		
		msg =
		      model.Switch( s.col, s.row, columnAtPoint( event.getLocation( ) ),
				    rowAtPoint( event.getLocation( ) ) );
		event.getDropTargetContext( ).dropComplete( true );
		if ( msg != null )
		    JOptionPane.showMessageDialog( this, msg, "Error", JOptionPane.ERROR_MESSAGE, null );
		else
		{ // make the columns the right width
		    for ( int i = 0; i < this.getColumnModel( ).getColumnCount( ); i++ )
		    {
			this.getColumnModel( ).getColumn( i ).setPreferredWidth( 300 );
			this.getColumnModel( ).getColumn( i ).setCellRenderer( getChildCellRenderer() );
		    }
		}
	    }
	    else
	    {
		event.rejectDrop( );
	    }
	}
	catch ( IOException exception )
	{
	    exception.printStackTrace( );
	    System.err.println( "Exception" + exception.getMessage( ) );
	    event.rejectDrop( );
	}
	catch ( UnsupportedFlavorException ufException )
	{
	    ufException.printStackTrace( );
	    System.err.println( "Exception" + ufException.getMessage( ) );
	    event.rejectDrop( );
	}
    }
    
    /**
     * is invoked if the use modifies the current drop gesture
     */
    
    public void dropActionChanged( DropTargetDragEvent event )
    {
    }
    
    /**
     * a drag gesture has been initiated
     */
    
    final static Team team = new Team( );
    
    public void dragGestureRecognized( DragGestureEvent event )
    {
	Object selected = team; // getSelectedValue();
	if ( selected != null )
	{
	    
	    CoordSelection objectSelection = new CoordSelection( new Coord( getSelectedRow( ), getSelectedColumn( ) ) );
	    
	    // as the name suggests, starts the dragging
	    dragSource.startDrag( event, DragSource.DefaultMoveDrop, objectSelection, this );
	}
	else
	{
	    // System.out.println( "nothing was selected");
	}
    }
    
    /**
     * this message goes to DragSourceListener, informing it that the dragging
     * has ended
     */
    
    public void dragDropEnd( DragSourceDropEvent event )
    {
	if ( event.getDropSuccess( ) )
	{
	    // removeElement();
	}
    }
    
    /**
     * this message goes to DragSourceListener, informing it that the dragging
     * has entered the DropSite
     */
    
    public void dragEnter( DragSourceDragEvent event )
    {
	// System.out.println( " dragEnter");
    }
    
    /**
     * this message goes to DragSourceListener, informing it that the dragging
     * has exited the DropSite
     */
    
    public void dragExit( DragSourceEvent event )
    {
	// System.out.println( "dragExit");
	
    }
    
    /**
     * this message goes to DragSourceListener, informing it that the dragging
     * is currently ocurring over the DropSite
     */
    
    public void dragOver( DragSourceDragEvent event )
    {
	// System.out.println( "dragExit");
	
    }
    
    /**
     * is invoked when the user changes the dropAction
     */
    
    public void dropActionChanged( DragSourceDragEvent event )
    {
	// System.out.println( "dropActionChanged");
    }
    
    /**
     * adds elements to itself
     */
    
    public void addElement( Object s )
    {
	((DefaultListModel) getModel( )).addElement( s.toString( ) );
    }
    
    /**
     * removes an element from itself
     */
    
    public void removeElement( )
    {
	// (( DefaultListModel)getModel()).removeElement( getSelectedValue());
    }

    public void setChildCellRenderer( ChildCellRenderer childCellRenderer )
    {
	this.childCellRenderer = childCellRenderer;
    }

    public ChildCellRenderer getChildCellRenderer( )
    {
	return childCellRenderer;
    }
    
}
